// ProductionFacilityBuildProject.cs
//
// Copyright (c) 2007 Mike Strobel
//
// This source code is subject to the terms of the Microsoft Reciprocal License (Ms-RL).
// For details, see <http://www.opensource.org/licenses/ms-rl.html>.
//
// All other rights reserved.

using System;
using System.Runtime.Serialization;
using System.Threading;

using Supremacy.Game;
using Supremacy.Orbitals;
using Supremacy.Resources;
using Supremacy.Universe;

namespace Supremacy.Economy
{
    [Serializable]
    public class ProductionFacilityBuildProject : BuildProject
    {
        private int colonyId;
        private int designId;

        public Colony Source
        {
            get { return GameContext.Current.Universe.Objects[colonyId] as Colony; }
        }

        public ProductionFacilityDesign FacilityDesign
        {
            get { return GameContext.Current.TechDatabase.ProductionFacilityDesigns[designId]; }
        }

        protected override int GetIndustryAvailable()
        {
            return Source.GetProductionOutput(ProductionCategory.Industry);
        }

        public ProductionFacilityBuildProject(
            Colony colony, 
            // ReSharper disable SuggestBaseTypeForParameter
            ProductionFacilityDesign target)
            // ReSharper restore SuggestBaseTypeForParameter
            : base(colony.Owner, colony, target)
        {
            if (colony == null)
                throw new ArgumentNullException("colony");
            if (target == null)
                throw new ArgumentNullException("target");
            designId = target.DesignID;
            colonyId = colony.ObjectID;
        }

        public override BuildProject CloneEquivalent()
        {
            return new ProductionFacilityBuildProject(this.Source, this.FacilityDesign);
        }
    }

    [Serializable]
    public class OrbitalBatteryBuildProject : BuildProject
    {
        [NonSerialized]
        private Lazy<Colony> _colony;

        public Colony Source
        {
            get { return _colony.Value; }
        }

        public OrbitalBatteryDesign OrbitalBatteryDesign
        {
            get { return base.BuildDesign as OrbitalBatteryDesign; }
        }

        protected override int GetIndustryAvailable()
        {
            return Source.GetProductionOutput(ProductionCategory.Industry);
        }

        public OrbitalBatteryBuildProject(Colony colony, OrbitalBatteryDesign target)
            : base(colony.Owner, colony, target)
        {
            if (colony == null)
                throw new ArgumentNullException("colony");
            if (target == null)
                throw new ArgumentNullException("target");

            _colony = new Lazy<Colony>(this.FindColony, LazyThreadSafetyMode.PublicationOnly);
        }

        private Colony FindColony()
        {
            return GameContext.Current.Universe.Map[this.Location].System.Colony;
        }

        public override BuildProject CloneEquivalent()
        {
            return new OrbitalBatteryBuildProject(this.Source, this.OrbitalBatteryDesign);
        }

        public override void SerializeOwnedData(IO.Serialization.SerializationWriter writer, object context)
        {
            base.SerializeOwnedData(writer, context);

            _colony = new Lazy<Colony>(this.FindColony, LazyThreadSafetyMode.PublicationOnly);
        }

        [OnDeserialized]
        private void OnDeserialized(StreamingContext context)
        {
            _colony = new Lazy<Colony>(this.FindColony, LazyThreadSafetyMode.PublicationOnly);
        }
    }

    [Serializable]
    public class ProductionFacilityUpgradeProject : ProductionFacilityBuildProject
    {
        private readonly int _baseTypeId;

        public override string Description
        {
            get
            {
                return String.Format(
                    ResourceManager.GetString("UPGRADE_FORMAT_STRING"),
                    ResourceManager.GetString(FacilityDesign.Name));
            }
        }

        protected ProductionFacilityDesign BaseFacilityType
        {
            get { return GameContext.Current.TechDatabase.ProductionFacilityDesigns[_baseTypeId]; }
        }

        protected override int IndustryRequired
        {
            get
            {
                int count = Source.GetTotalFacilities(BaseFacilityType.Category);
                int unitCost = (int)(0.50 * base.IndustryRequired);
                return (count * unitCost);
            }
        }

        protected override ResourceValueCollection ResourcesRequired
        {
            get { return new ResourceValueCollection(); }
        }

        public override bool IsUpgrade
        {
            get { return true; }
        }

        public override void Finish()
        {
            this.Source.SetFacilityType(FacilityDesign.Category, FacilityDesign);

            var civManager = GameContext.Current.CivilizationManagers[Builder];
            if (civManager == null)
                return;

            civManager.SitRepEntries.Add(new ItemBuiltSitRepEntry(Builder, BuildDesign, Location));
        }

        public ProductionFacilityUpgradeProject(Colony colony, ProductionFacilityDesign target)
            : base(colony, target)
        {
            _baseTypeId = colony.GetFacilityType(target.Category).DesignID;
        }

        public override BuildProject CloneEquivalent()
        {
            return null;
        }
    }

    [Serializable]
    public class OrbitalBatteryUpgradeProject : OrbitalBatteryBuildProject
    {
        private readonly int _baseTypeId;

        public override string Description
        {
            get
            {
                return string.Format(
                    ResourceManager.GetString("UPGRADE_FORMAT_STRING"),
                    ResourceManager.GetString(OrbitalBatteryDesign.Name));
            }
        }

        protected OrbitalBatteryDesign BaseOrbitalBatteryDesign
        {
            get { return GameContext.Current.TechDatabase.OrbitalBatteryDesigns[_baseTypeId]; }
        }

        protected override int IndustryRequired
        {
            get
            {
                var count = Source.TotalOrbitalBatteries;
                var unitCost = (int)(0.50 * base.IndustryRequired);
                return (count * unitCost);
            }
        }

        protected override ResourceValueCollection ResourcesRequired
        {
            get
            {
                var result = new ResourceValueCollection();
                return result;
            }
        }

        public override bool IsUpgrade
        {
            get { return true; }
        }

        public override void Finish()
        {
            var civManager = GameContext.Current.CivilizationManagers[Builder];
            
            this.Source.OrbitalBatteryDesign = OrbitalBatteryDesign;
            
            if (civManager != null)
            {
                civManager.SitRepEntries.Add(
                    new ItemBuiltSitRepEntry(Builder, BuildDesign, Location));
            }
        }

        public OrbitalBatteryUpgradeProject(Colony colony, OrbitalBatteryDesign target)
            : base(colony, target)
        {
            _baseTypeId = colony.OrbitalBatteryDesign.DesignID;
        }

        public override BuildProject CloneEquivalent()
        {
            return null;
        }
    }
}
